package com.syx.migration.utils;

import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class BeanMapUtils {

    /**
     * 集合map转集合bean
     */
    public static <T> List<T> mapListToBeanList(List<Map<String, Object>> maps, Class<T> beanClass) {
        ArrayList<T> list = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            list.add(mapToBean(map, beanClass));
        }
        return list;
    }


    /**
     * 利用反射将map集合封装成bean对象
     * @param map
     * @param clazz
     * @return
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<?> clazz){
        try {
            Object obj = clazz.newInstance();
            if (map != null && !map.isEmpty() && map.size() > 0) {
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    // 属性名
                    String propertyName = entry.getKey();
                    // 属性值
                    Object value = entry.getValue();
                    String setMethodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                    //获取和map的key匹配的属性名称
                    Field field = getClassField(clazz, propertyName);
                    if (field == null) {
                        continue;
                    }
                    Class<?> fieldTypeClass = field.getType();
                    value = convertValType(value, fieldTypeClass);
                    clazz.getMethod(setMethodName, field.getType()).invoke(obj, value);
                }
            }
            return (T) obj;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(map);
            throw new RuntimeException("map转bean异常:");
        }
    }

    /**
     * 根据给定对象类匹配对象中的特定字段
     * @param clazz
     * @param fieldName
     * @return
     */
    private static Field getClassField(Class<?> clazz, String fieldName) {
        if (Object.class.getName().equals(clazz.getName())) {
            return null;
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }
        //如果该类还有父类，将父类对象中的字段也取出
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {
            //递归获取
            return getClassField(superClass, fieldName);
        }
        return null;
    }

    /**
     * 将map的value值转为实体类中字段类型匹配的方法
     * @param value
     * @param fieldTypeClass
     * @return
     */
    private static Object convertValType(Object value, Class<?> fieldTypeClass) throws ParseException {
        Object retVal = null;
        if (Long.class.getName().equals(fieldTypeClass.getName())
                || long.class.getName().equals(fieldTypeClass.getName())) {
            if(value == null || value.toString().isEmpty()){
                retVal = 0L;
            } else {
                value = value.toString().replace("-","").replace("【", "").replace("年", "").replace("月","").replace("】", "").trim();
                retVal = Long.parseLong(value.toString());
            }
        } else if (Integer.class.getName().equals(fieldTypeClass.getName())
                || int.class.getName().equals(fieldTypeClass.getName())) {
            if(value == null || value.toString().isEmpty()){
                retVal = 0;
            } else {
                retVal = Integer.parseInt(value.toString());
            }
        } else if (Float.class.getName().equals(fieldTypeClass.getName())
                || float.class.getName().equals(fieldTypeClass.getName())) {
            if(value == null || value.toString().isEmpty()){
                retVal = 0.0f;
            } else {
                retVal = Float.parseFloat(value.toString());
            }
        } else if (Double.class.getName().equals(fieldTypeClass.getName())
                || double.class.getName().equals(fieldTypeClass.getName())) {
            if(value == null || value.toString().isEmpty()){
                retVal = 0.0;
            } else {
                retVal = Double.parseDouble(value.toString());
            }
        } else if (Date.class.getName().equals(fieldTypeClass.getName())) {
            if(!(value == null || value.toString().isEmpty())){
                if(isValidDateFormat(value.toString(), "yyyy-MM-dd HH:mm:ss")){
                    retVal = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value.toString());
                }else if(isValidDateFormat(value.toString(), "yyyy-MM-dd")){
                    retVal = new SimpleDateFormat("yyyy-MM-dd").parse(value.toString());
                } else if(isValidDateFormat(value.toString(), "MM/dd/yyyy HH:mm:ss")){
                    retVal = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(value.toString());
                }  else if(isValidDateFormat(value.toString(), "MM/dd/yyyy")){
                    retVal = new SimpleDateFormat("MM/dd/yyyy").parse(value.toString());
                } else if(isValidDateFormat(value.toString(), "dd/MM/yyyy HH:mm:ss")){
                    retVal = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").parse(value.toString());
                } else if(isValidDateFormat(value.toString(), "dd/MM/yyyy")){
                    retVal = new SimpleDateFormat("dd/MM/yyyy").parse(value.toString());
                } else if(isValidDateFormat(value.toString(), "yyyy/MM/dd HH:mm:ss")){
                    retVal = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(value.toString());
                } else if(isValidDateFormat(value.toString(), "yyyy/MM/dd")){
                    retVal = new SimpleDateFormat("yyyy/MM/dd").parse(value.toString());
                }
            }
        } else if (BigDecimal.class.getName().equals(fieldTypeClass.getName())) {
            if(value == null || value.toString().isEmpty()){
                retVal = new BigDecimal("0");
            } else {
                if (isBigDecimal(value.toString())){ // 判断是否为bigDecimal
                    retVal = new BigDecimal(value.toString());
                }else{
                    retVal = new BigDecimal("0");
                }
            }
        } else if (String.class.getName().equals(fieldTypeClass.getName())) {
            if(!(value == null || value.toString().isEmpty())){
                retVal = value.toString();
            }
        }else {
            retVal = value;
        }
        return retVal;
    }

    public static boolean isValidDateFormat(String dateString, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        // 设置严格模式，不允许解析不严格匹配的日期
        sdf.setLenient(false);
        try {
            sdf.parse(dateString);
            // 解析成功，返回true
            return true;
        } catch (ParseException e) {
            // 解析异常，返回false
            return false;
        }
    }

    public static boolean isBigDecimal(String str){
        if(str==null || str.trim().length() == 0){
            return false;
        }
        char[] chars = str.toCharArray();
        int sz = chars.length;
        int i = (chars[0] == '-') ? 1 : 0;
        if(i == sz) return false;

        if(chars[i] == '.') return false;//除了负号，第一位不能为'小数点'

        boolean radixPoint = false;
        for(; i < sz; i++){
            if(chars[i] == '.'){
                if(radixPoint) return false;
                radixPoint = true;
            }else if(!(chars[i] >= '0' && chars[i] <= '9')){
                return false;
            }
        }
        return true;
    }
}
